/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package newvideoplayer;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.Timer;
import newvideoplayer.KeyFrame;
import newvideoplayer.MetaFile;

/**
 * 
 * @author Aishwarya
 */

public class NewVideoPlayer extends javax.swing.JFrame {

	public ArrayList<MetaFile> metaSet = new ArrayList<MetaFile>();
	MetaFile m = new MetaFile();
	Thread[] linkVideos = new Thread[10];
	int RED_Count;
	File primaryVideo = null;
	int videoNumber = 0;
	InputStream is;
	JLabel[] labelArray;
	int width = 352;
	int height = 288;
	BufferedImage[] imageArray;
	BufferedImage img;
	private javax.swing.JPanel ControlPanel;
	private javax.swing.JLabel DisplayLabel;
	private javax.swing.JMenu File;
	private javax.swing.JMenuBar MenuBar;
	private javax.swing.JMenuItem Open;
	private javax.swing.JButton Pause;
	private javax.swing.JButton Play;
	private javax.swing.JButton Stop;
	private javax.swing.JSplitPane jSplitPane1;

	// Variables reqd for interpolation
	int RectTopX;
	int rectTopY;
	int rectBottomX;
	int rectBottomY;
	int prevKF = 0;
	int currentKF = 1;
	float topLeftXInc = 0, topRightXInc = 0, botLeftXInc = 0, botRightXInc = 0,
			topLeftYInc = 0, topRightYInc = 0, botLeftYInc = 0,
			botRightYInc = 0;

	int LabelIndex;
	int counter1 = 0;
	int DELAY = 1000 / 30;
	Timer fps;
	Rectangle currentRect = new Rectangle();
	Thread VideoThread;

	public NewVideoPlayer() {
		System.out.println("in constructor");
		initComponents();
	}

	private void initComponents() {

		jSplitPane1 = new javax.swing.JSplitPane();
		DisplayLabel = new javax.swing.JLabel();
		ControlPanel = new javax.swing.JPanel();
		Stop = new javax.swing.JButton();
		Pause = new javax.swing.JButton();
		Play = new javax.swing.JButton();
		MenuBar = new javax.swing.JMenuBar();

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		setPreferredSize(new java.awt.Dimension(355, 410));

		/*
		 * Vertically split the Panel into two. Bottom part has the play, pause
		 * and stop buttons
		 */
		jSplitPane1.setBorder(javax.swing.BorderFactory
				.createLineBorder(new java.awt.Color(0, 0, 0)));
		jSplitPane1.setDividerLocation(290);
		jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

		/*
		 * Set the dimensions of the label, top part of the above panel
		 */
		DisplayLabel.setMaximumSize(new java.awt.Dimension(352, 288));
		DisplayLabel.setMinimumSize(new java.awt.Dimension(352, 288));
		DisplayLabel.setPreferredSize(new java.awt.Dimension(352, 288));
		jSplitPane1.setTopComponent(DisplayLabel);

		ControlPanel.setAlignmentX(0.0F);
		ControlPanel.setAlignmentY(0.0F);
		ControlPanel.setMaximumSize(new java.awt.Dimension(32767, 130));
		ControlPanel.setMinimumSize(new java.awt.Dimension(0, 25));
		ControlPanel.setPreferredSize(new java.awt.Dimension(652, 20));

		Stop.setText("Stop");
		Stop.setAlignmentY(0.0F);
		Stop.setVerticalAlignment(javax.swing.SwingConstants.TOP);
		Stop.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				StopActionPerformed(evt);
			}
		});

		Pause.setText("Pause");
		Pause.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				PauseActionPerformed(evt);
			}
		});

		Play.setText("Play");
		Play.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				PlayActionPerformed(evt);
			}
		});

		javax.swing.GroupLayout ControlPanelLayout = new javax.swing.GroupLayout(
				ControlPanel);
		ControlPanel.setLayout(ControlPanelLayout);
		ControlPanelLayout
				.setHorizontalGroup(ControlPanelLayout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								ControlPanelLayout
										.createSequentialGroup()
										.addGap(30, 30, 30)
										.addComponent(
												Play,
												javax.swing.GroupLayout.PREFERRED_SIZE,
												80,
												javax.swing.GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(
												javax.swing.LayoutStyle.ComponentPlacement.RELATED)
										.addComponent(
												Pause,
												javax.swing.GroupLayout.PREFERRED_SIZE,
												80,
												javax.swing.GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(
												javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
										.addComponent(
												Stop,
												javax.swing.GroupLayout.PREFERRED_SIZE,
												80,
												javax.swing.GroupLayout.PREFERRED_SIZE)
										.addContainerGap(354, Short.MAX_VALUE)));
		ControlPanelLayout
				.setVerticalGroup(ControlPanelLayout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								ControlPanelLayout
										.createSequentialGroup()
										.addContainerGap()
										.addGroup(
												ControlPanelLayout
														.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
														.addComponent(Play)
														.addComponent(Pause)
														.addComponent(Stop))
										.addContainerGap(76, Short.MAX_VALUE)));

		jSplitPane1.setBottomComponent(ControlPanel);
		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
				getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout.createParallelGroup(
				javax.swing.GroupLayout.Alignment.LEADING).addComponent(
				jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING,
				javax.swing.GroupLayout.PREFERRED_SIZE, 654,
				javax.swing.GroupLayout.PREFERRED_SIZE));
		layout.setVerticalGroup(layout.createParallelGroup(
				javax.swing.GroupLayout.Alignment.LEADING).addGroup(
				javax.swing.GroupLayout.Alignment.TRAILING,
				layout.createSequentialGroup().addComponent(jSplitPane1,
						javax.swing.GroupLayout.PREFERRED_SIZE, 405,
						javax.swing.GroupLayout.PREFERRED_SIZE).addGap(0, 0,
						Short.MAX_VALUE)));

		pack();
		showNewVideo("E:\\CSCI576\\project\\vdo6.rgb");
		// VideoProcessing("E:\\CSCI576\\project\\vdo6.rgb");
		// Display();
	}

	private void PauseActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		fps.stop();
	}

	private void PlayActionPerformed(java.awt.event.ActionEvent evt) {
		// VideoThread.interrupt();
		fps.start();
	}

	private void StopActionPerformed(java.awt.event.ActionEvent evt) {
		counter1 = 0;
		DisplayLabel.setIcon(new ImageIcon(imageArray[counter1]));
		fps.stop();

		// showNewVideo("E:\\CSCI576\\project\\vdo7.rgb");

	}

	public void showNewVideo(final String path) {
		try {
			for (int i = 0; i < 10; i++) {
				if (linkVideos[i] != null) {
					System.out.println("Inside if(linkVideos[i]!=null)");
					linkVideos[i].join();
				}
			}
		} catch (InterruptedException ex) {
			Logger.getLogger(NewVideoPlayer.class.getName()).log(Level.SEVERE,
					null, ex);
		}

		linkVideos[videoNumber] = new Thread(new Runnable() {
			// @Override
			public void run() {

				// readMeta();

				// new method.....chinmay.....@7:15
				try {
					readMyMeta();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				VideoProcessing(path);
				// Display();

			}
		});
		linkVideos[videoNumber].start();
		videoNumber++;
	}

	public void VideoProcessing(String readPath) {
		try {
			primaryVideo = new File(readPath);
			is = new FileInputStream(primaryVideo);
		} catch (FileNotFoundException e) {
			System.out.println("File not found!!");
		}
		final long len = primaryVideo.length();
		System.out.println("file.len :" + len);
		// byte[] bytes = new byte[(int)len];
		int numRead = 0;

		labelArray = new JLabel[(int) (primaryVideo.length() / (3 * height * width))];// equals
																						// total
																						// number
																						// of
																						// frames
		RED_Count = labelArray.length;// RED_COUNT keeps track of frame being
										// displayed
		imageArray = new BufferedImage[(int) (primaryVideo.length() / (3 * height * width))];
		// SourceSlider.setMaximum(labelArray.length);
		LabelIndex = labelArray.length;
		try {
            System.out.println("labelArray.length : " + labelArray.length);

            ActionListener actionPerformed;
            System.out.println("metaData.size() = " + metaSet.size());
            actionPerformed = new ActionListener() {
                    int numRead = 0;
                    int currentFrame;
                    byte[] bytes = new byte[(int) len];

                    // @Override
                    public void actionPerformed(ActionEvent e) {
                            if (RED_Count > 0) {
                                    currentFrame = 720 - RED_Count;
                                    try {
                                            if ((numRead = is
                                                            .read(bytes, 0, 3 * height * width)) >= 0) {
                                                    // System.out.println("inside while : " +
                                                    // RED_Count);
                                                    int ind = 0;
                                                    img = new BufferedImage(width, height,
                                                                    BufferedImage.TYPE_INT_RGB);
                                                    for (int y = 0; y < height; y++) {
                                                            for (int x = 0; x < width; x++) {
                                                                    byte a = 0;
                                                                    byte r = bytes[ind];
                                                                    byte g = bytes[ind + height * width];
                                                                    byte b = bytes[ind + height * width * 2];
                                                                    int pix = 0xff000000
                                                                                    | ((r & 0xff) << 16)
                                                                                    | ((g & 0xff) << 8)
                                                                                    | (b & 0xff);
                                                                    img.setRGB(x, y, pix);
                                                                    ind++;
                                                            }
                                                    }

                                                    for (int p = 0; p < metaSet.size(); p++) {

                                                            // System.out.println("DEBUG !!!!");
                                                            int nextKf=metaSet.get(p).nextKf;
                                                            int prevKf=metaSet.get(p).prevKf;

                                                            if (metaSet.get(p).kf.get(prevKf).frameNum <= currentFrame
                                                                            && currentFrame <= metaSet.get(p).kf
                                                                                            .get(nextKf).frameNum) {
                                                           
                                                                    calcIncrement(metaSet.get(p).kf.get(nextKf).frameNum,p);
                                                                    interpolateArea(currentFrame, p);
                                                            } else {
                                                                    DisplayLabel.setCursor(Cursor
                                                                                    .getDefaultCursor());
                                                            }
                                                            
                                                            
                                                            
                                                    }
                                                    //Change the next and current keyframe index
                                                    for(int p=0;p<metaSet.size();p++)
                                                    {
                                                        int nextKf=metaSet.get(p).nextKf;
                                                        if(currentFrame==metaSet.get(p).kf.get(nextKf).frameNum)
                                                        {
                                                            
                                                            if(metaSet.get(p).nextKf<metaSet.get(p).numOfKeyFrames-1)
                                                            {
                                                                metaSet.get(p).nextKf++;
                                                                //System.out.println("``````````````````````next key frames next="+metaSet.get(p).nextKf+"no of kf="+metaSet.get(p).numOfKeyFrames);
                                                            }
                                                            metaSet.get(p).prevKf++;
                                                        }
                                                    }

                                                    DisplayLabel.setIcon(new ImageIcon(img));
                                                    RED_Count--;
                                            }
                                    } catch (IOException ex) {
                                            Logger.getLogger(NewVideoPlayer.class.getName()).log(
                                                            Level.SEVERE, null, ex);
                                    }
                            } else {
                                    // all frames displayed, loop the video
                                    for(int p=0;p<metaSet.size();p++)
                                    {
                                        metaSet.get(p).prevKf=0;
                                        metaSet.get(p).nextKf=1;
                                    }RED_Count = labelArray.length;
                                    try {
                                            is = new FileInputStream(primaryVideo);
                                    } catch (FileNotFoundException ex) {
                                            Logger.getLogger(NewVideoPlayer.class.getName()).log(
                                                            Level.SEVERE, null, ex);
                                    }
                                    System.out.println("Reached the end " + RED_Count);
                            }
                    }
            };
                fps = new Timer(DELAY, actionPerformed);
			fps.start();
		} catch (Exception e) {
		}
	}

	public void interpolateArea(int FrameNumber, int p) {

		int currTopLeftX = 0;
		int currTopLeftY = 0;
		int currBotRightX = 0;
		int currBotRightY = 0;
                int nextKf=metaSet.get(p).nextKf;
                int prevKf=metaSet.get(p).prevKf;

		currTopLeftX = (int)((FrameNumber - metaSet.get(p).kf.get(prevKf).frameNum) * topLeftXInc)
				+ metaSet.get(p).kf.get(prevKf).topLeftX;
		currTopLeftY = (int)((FrameNumber - metaSet.get(p).kf.get(prevKf).frameNum) * topLeftYInc)
				+ metaSet.get(p).kf.get(prevKf).topLeftY;
		currBotRightX = (int)((FrameNumber - metaSet.get(p).kf.get(prevKf).frameNum) * botRightXInc)
				+ metaSet.get(p).kf.get(prevKf).bottomRightX;
		currBotRightY = (int)((FrameNumber - metaSet.get(p).kf.get(prevKf).frameNum) * botRightYInc)
				+ metaSet.get(p).kf.get(prevKf).bottomRightY;

                                
                Graphics g=getGraphics();
                g.setColor(Color.red);
                
                g.drawRect(currTopLeftX, currTopLeftY,currBotRightX-currTopLeftX , currBotRightY-currTopLeftY);

		DisplayLabel.paintImmediately(currTopLeftX, currTopLeftY, currBotRightX
				- currTopLeftX, currBotRightY - currTopLeftY);
		Point mousePoint = MouseInfo.getPointerInfo().getLocation();

		if (currTopLeftX <= mousePoint.getX()
				&& mousePoint.getX() <= currBotRightX) {
			if (currTopLeftY <= mousePoint.getY()
					&& mousePoint.getY() <= currBotRightY)
				DisplayLabel.setCursor(Cursor
						.getPredefinedCursor(Cursor.HAND_CURSOR));
		} else
			DisplayLabel.setCursor(Cursor.getDefaultCursor());
	}

public void calcIncrement(int endFrame, int p) {

                float frameDiff=endFrame - metaSet.get(p).kf.get(0).frameNum;
                System.out.println("frame Diff"+frameDiff);
                System.out.println("Yes.");
		if ((frameDiff) != 0) {
                    
			topLeftXInc = (metaSet.get(p).kf.get(1).topLeftX - metaSet
					.get(p).kf.get(0).topLeftX)
					/ (frameDiff);
			topLeftYInc = (metaSet.get(p).kf.get(1).topLeftY - metaSet
					.get(p).kf.get(0).topLeftY)
					/ (frameDiff);

			botRightXInc = (metaSet.get(p).kf.get(1).bottomRightX - metaSet
					.get(p).kf.get(0).bottomRightX)
					/ (frameDiff);
                        //System.out.println("Bot right X"+botRightXInc);
			botRightYInc = (metaSet.get(p).kf.get(1).bottomRightY - metaSet
					.get(p).kf.get(0).bottomRightY)
					/ (frameDiff);
		}
	}

/*
	public void readGeneralInfo(String buffer) {

		String temp = "";
		int i = 0;
		while (buffer.charAt(i) != ' ') {
			temp += buffer.charAt(i);
			i++;
		}

		m.rectID = Integer.parseInt(temp);
		System.out.println("");
		temp = "";

		while (buffer.charAt(i) == ' ')
			i++;

		while (buffer.charAt(i) != ' ')
			temp += buffer.charAt(i++);
		m.rectName = temp;
		temp = "";

		while (buffer.charAt(i) == ' ')
			i++;

		while (i < buffer.length()) {
			System.out.println(buffer.charAt(i));
			temp += buffer.charAt(i);
			i++;
		}

		m.numOfKeyFrames = Integer.parseInt(temp);
		temp = "";

	}

	public void readVideoInfo(String buffer) {
		int i = 0;
		String temp = "";

		while (buffer.charAt(i) != ' ')
			temp += buffer.charAt(i++);
		m.linkedVideoName = temp;
		temp = "";

		while (buffer.charAt(i) == ' ')
			i++;

		while (i < buffer.length()) {
			temp += buffer.charAt(i);
			i++;
		}
		m.linkedVideoStartFrame = Integer.parseInt(temp);

	}

	public void readKeyFrames(BufferedReader buf) {
		try {
			int i = 0;
			String temp = "", sCurrentLine = "";
			for (int j = 0; j < m.numOfKeyFrames; j++) {

				i = 0;
				sCurrentLine = buf.readLine();
				while (sCurrentLine.charAt(i) != ' ')
					temp += sCurrentLine.charAt(i++);
				KeyFrame k = new KeyFrame();
				k.frameNum = Integer.parseInt(temp);
				temp = "";

				while (sCurrentLine.charAt(i) == ' ')
					i++;

				// LeftTopX
				while (sCurrentLine.charAt(i) != ' ')
					temp += sCurrentLine.charAt(i++);
				k.topLeftX = Integer.parseInt(temp);
				temp = "";

				while (sCurrentLine.charAt(i) == ' ')
					i++;
				// LeftTopY
				while (sCurrentLine.charAt(i) != ' ')
					temp += sCurrentLine.charAt(i++);
				k.topLeftY = Integer.parseInt(temp);
				temp = "";

				while (sCurrentLine.charAt(i) == ' ')
					i++;

				// RigthBottomX
				while (sCurrentLine.charAt(i) != ' ')
					temp += sCurrentLine.charAt(i++);
				k.bottomRightX = Integer.parseInt(temp);
				temp = "";

				while (sCurrentLine.charAt(i) == ' ')
					i++;

				// RightBottomY
				while (i < sCurrentLine.length()) {
					temp += sCurrentLine.charAt(i);
					i++;
				}
				k.bottomRightY = Integer.parseInt(temp);
				temp = "";
				m.kf.add(k);
			}
		} catch (FileNotFoundException ex) {
			Logger.getLogger(NewVideoPlayer.class.getName()).log(Level.SEVERE,
					null, ex);
		} catch (IOException ex) {
			Logger.getLogger(NewVideoPlayer.class.getName()).log(Level.SEVERE,
					null, ex);
		}
	}

	public void readHyperLink() {

	}

	public void readMeta() {

		BufferedReader bf;
		try {

			String sCurrentLine;
			int i = 0;
			bf = new BufferedReader(new FileReader("vdo6.meta"));

			while ((sCurrentLine = bf.readLine()) != null) {
				System.out.println("IMPPPP" + sCurrentLine);
				// Process Line one (rectID, RectName,NoOfKeyFrames)
				m = new MetaFile();
				readGeneralInfo(sCurrentLine);

				// Process Line two(Link video name, link video frame no)
				sCurrentLine = bf.readLine();
				readVideoInfo(sCurrentLine);

				// Process keyframe data

				readKeyFrames(bf);
				for (int num = 0; num < m.numOfKeyFrames; num++) {
					bf.readLine();
				}
				metaSet.add(m);
			}
			int num = 0;
			while (num < metaSet.size()) {
				metaSet.get(num++).display();
				System.out.println(metaSet.size());
			}

		} catch (FileNotFoundException ex) {
			Logger.getLogger(NewVideoPlayer.class.getName()).log(Level.SEVERE,
					null, ex);
		} catch (IOException e) {
			System.out.println("IOException");
		}

		/*
		 * rectTopX=100; rectTopY=100; rectBottomX=160; rectBottomY=190;
		 
	}
*/
	public void readMyMeta() throws Exception {

		BufferedReader bufferedReader = new BufferedReader(new FileReader(
				"vdo6.meta"));

		String sCurrentLine;
		sCurrentLine = bufferedReader.readLine();
		String result[];

		while (sCurrentLine != null) {
			m = new MetaFile();
			result = sCurrentLine.split(" ");

			if (result.length == 3) {
				m.rectID = Integer.parseInt(result[0]);
				m.rectName = result[1];
				m.numOfKeyFrames = Integer.parseInt(result[2]);
				System.out.println("m.numOfKeyFrames" + m.numOfKeyFrames);
				sCurrentLine = bufferedReader.readLine();
				result = sCurrentLine.split(" ");
			}
			if (result.length == 2) {

				m.linkedVideoName = result[0];
				m.linkedVideoStartFrame = Integer.parseInt(result[1]);
				sCurrentLine = bufferedReader.readLine();
				result = sCurrentLine.split(" ");
			}
			if (result.length == 5) {

				for (int i = 0; i < m.numOfKeyFrames; i++) {

					KeyFrame k = new KeyFrame();
					k.frameNum = Integer.parseInt(result[0]);
					k.topLeftX = Integer.parseInt(result[1]);
					k.topLeftY = Integer.parseInt(result[2]);
					k.bottomRightX = Integer.parseInt(result[3]);
					k.bottomRightY = Integer.parseInt(result[4]);

					m.kf.add(k);

					if (i == (m.numOfKeyFrames) - 1)
						break;
					sCurrentLine = bufferedReader.readLine();
					result = sCurrentLine.split(" ");

				}
				sCurrentLine = bufferedReader.readLine();

			}

			metaSet.add(m);
		}

		// display the newly populated metaFile

		int num = 0;
		while (num < metaSet.size()) {
			metaSet.get(num++).display();
		}

	}

	/*
	 public void Play(int counter1)
	    {

	            Point mousePoint=MouseInfo.getPointerInfo().getLocation();
	            if(rectTopX<=mousePoint.getX() && mousePoint.getX()<=rectBottomX)
	            {   if(rectTopY<=mousePoint.getY() && mousePoint.getY()<=rectBottomY)
	                       DisplayLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
	            }
	            else
	                    DisplayLabel.setCursor(Cursor.getDefaultCursor());
	            DisplayLabel.setIcon(new ImageIcon(imageArray[counter1]));
	            LabelIndex++;
	    }
	 */
	public static void main(String[] args) {
		new NewVideoPlayer().setVisible(true);
	}
}
